/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package videosearch;

import java.awt.image.BufferedImage;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
import java.util.ArrayList;

/**
 *
 * @author John This class is designed to ingest a .rgb file in a separate
 * thread and update a list with new frame objects
 */
public class RGBIngestor implements Runnable {

    static final int Width = 352; // Width of input video
    static final int Height = 288; // Height of input video
    private ArrayList<BufferedImage> data; // data
    private ArrayList<BufferedImage> framesRead; // frames we've read in
    private String fileName; // filename of the file to read in

    // Constructor requires the name of the file to ingest, and the array to
    //  push the data to.
    public RGBIngestor(String file, ArrayList<BufferedImage> data) {
        this.fileName = file;
        this.data = data;
        framesRead = new ArrayList<>();
    }

    // This method updates the data array, which is a pointer into the main
    //  thread, where the gui will read from it
    protected void updateProgress() {
        // Add frames from the framesRead array, then clear the frames read
        for (BufferedImage frame : framesRead) {
            data.add(frame);
        }
        framesRead.clear();
    }

    // Override because this is a runnable, this is what gets called when we
    //  start the thread made with this class
    @Override
    public void run() {
        BufferedImage img = null;
        File file = null;
        InputStream is = null;

        try {
            // Open .rgb file up
            file = new File(fileName);
            is = new FileInputStream(file);

            // variables for reading in data
            int frameCount = 0;
            int frameLength = Width * Height * 3;
            byte[] bytes = new byte[frameLength];

            // read in the data as binary bytes
            while (is.read(bytes) >= 0) {
                frameCount++; // new frame
                img = new BufferedImage(Width, Height, BufferedImage.TYPE_INT_RGB);
                int ind = 0;
                for (int y = 0; y < Height; y++) { // iterate over height
                    for (int x = 0; x < Width; x++) { // iterate over width
                        byte r = bytes[ind];
                        byte g = bytes[ind + Height * Width];
                        byte b = bytes[ind + Height * Width * 2];

                        int pix = 0xff000000 | ((r & 0xff) << 16) | // a pixel in rgb
                                ((g & 0xff) << 8) | (b & 0xff); // is 0xFFRRGGBB
                        img.setRGB(x, y, pix); // set pixels in the image
                        ind++;
                    }
                }
                framesRead.add(img); // queue the frames read in
                if (frameCount % 5 == 0) {
                    updateProgress(); // add them to the main thread to be displayed
                }
            }
        } catch (FileNotFoundException e) {
            System.out.println("Couldn't find the file: " + fileName);
            System.out.println(e.getMessage());
        } catch (IOException e) {
            System.out.println("IO Exception occured");
            System.out.println(e.getMessage());
        } finally {
            closeInputStream(is); // always close the input stream
        }
    }

    // function to ensure the input stream gets closed
    private void closeInputStream(InputStream stream) {
        try {
            if (stream != null) {
                stream.close();
            }
        } catch (IOException e) {
            System.out.println("IO Exception occured");
            System.out.println(e.getMessage());
        }
    }
}
